package com.mapfinal.gis.controller;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;

import com.jfinal.kit.PathKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.lambkit.common.util.AttachmentUtils;
import com.lambkit.db.mgr.MgrTable;
import com.lambkit.db.sql.condition.ConditionBuilder;
import com.lambkit.db.sql.condition.SqlBuilder;
import com.lambkit.module.meta.model.MetaFile;
import com.lambkit.module.meta.model.MetaFileCatalogMapping;
import com.lambkit.module.meta.service.MetaFileCatalogMappingService;
import com.lambkit.module.meta.service.MetaFileService;
import com.lambkit.web.controller.LambkitController;

public class FileController extends LambkitController {

	/**
	 * 获取某一doc的信息
	 */
	public void index() {
		MetaFileService service = MetaFile.service();
		if(service==null) {
			renderJson(Ret.fail().set("msg", "service is null"));
			return;
		}
		MgrTable tbc = getTableView(service.getTableName(), true);
		if (tbc == null) {
			renderJson(Ret.fail().set("msg", "table is not find."));
			return;
		}
		String model_id = getPara(0, getPara("id"));
		if (StrKit.notBlank(model_id)) {
			MetaFile model = service.findById(Long.valueOf(model_id));
			renderJson(Ret.ok().set("data", model));
		} else {
			renderJson(Ret.fail().set("msg", "id is null"));
		}
	}

	/**
	 * 获取doc列表
	 */
	public void list() {
		MetaFileService service = MetaFile.service();
		if(service==null) {
			renderJson(Ret.fail().set("msg", "service is null"));
			return;
		}
		MgrTable tbc = getTableView(service.getTableName(), true);
		if (tbc == null) {
			renderJson(Ret.fail().set("msg", "table is not find."));
			return;
		}
		SqlBuilder sb = new SqlBuilder();
		String select = sb.appendSelect(tbc).build();
		String sql = sb.clear().appendFrom(tbc).build();
		Integer pNumber = getParaToInt(1, 1);
		Integer pSize = getParaToInt(0, 15);
		Page<Record> page = Db.paginate(pNumber, pSize, select, sql);
		renderJson(Ret.ok().set("data", page));
	}

	/**
	 * 获取doc列表
	 */
	public void page() {
		MetaFileService service = MetaFile.service();
		if(service==null) {
			renderJson(Ret.fail().set("msg", "service is null"));
			return;
		}
		MgrTable tbc = getTableView(service.getTableName(), true);
		if (tbc == null) {
			renderJson(Ret.fail().set("msg", "table is not find."));
			return;
		}
		
		ConditionBuilder cb = getConditionsSQL(tbc).build("");
		SqlBuilder sb = new SqlBuilder();
		String select = sb.appendSelect(tbc).build();
		sb.clear().appendFrom(tbc).appendConditions(cb);
		String flags = getPara("flags");
		if(StrKit.notBlank(flags)) {
			StringBuilder strb = new StringBuilder();
			String[] flagsArry = flags.split(",");
			int i=0;
			for (String flag : flagsArry) {
				if(StrKit.notBlank(flag)) {
					if(i>0) strb.append(" and ");
					strb.append(" flag like '%").append(flag).append(",%'");
					i++;
				}
			}
			if(strb.length()>10) {
				sb.append(" and (").append(strb.toString()).append(") ");
			}
		}
		String sql = sb.build();
		Integer pNumber = getParaToInt(1, getParaToInt("pageNum", 1));
		Integer pSize = getParaToInt(0, getParaToInt("numPerPage", 15));
		Page<Record> page = Db.paginate(pNumber, pSize, select, sql, cb.getSqlParas());
		renderJson(Ret.ok().set("data", page));
	}
	
	public void rename() {
		Long id = getParaToLong("id");
		if(id==null) {
			renderJson(Ret.fail().set("msg", "id is null"));
			return;
		}
		String title = getPara("title");
		if(StrKit.isBlank(title)) {
			renderJson(Ret.fail().set("msg", "title is null"));
			return;
		}
		MetaFile file = MetaFile.service().findById(id);
		file.setTitle(title);
		boolean flag = file.update();
		if(flag) {
			renderJson(Ret.ok());
		} else {
			renderJson(Ret.fail());
		}
	}
	
	/**
	 * 删除file，并移除目录关系
	 */
	public void delete() {
		String ids = getPara("ids");
		if(StrKit.isBlank(ids)) {
			renderJson(Ret.fail().set("msg", "ids is null"));
			return;
		}
		int n = MetaFile.service().delete(ids);
		if(n > 0) {
			MetaFileCatalogMapping.service().removeFile(ids);
			renderJson(Ret.ok().set("num", n));
		} else {
			renderJson(Ret.fail());
		}
	}
	
	/**
	 * 不删除file，仅移除目录关系
	 */
	public void remove() {
		Long cid = getParaToLong("cid");
		String ids = getPara("ids");
		if(cid==null) {
			renderJson(Ret.fail().set("msg", "cid is null"));
			return;
		}
		if(StrKit.isBlank(ids)) {
			renderJson(Ret.fail().set("msg", "ids is null"));
			return;
		}
		int n = MetaFileCatalogMapping.service().removeFile(cid, ids);
		MetaFile.service().remove(ids);
		if(n > 0) {
			renderJson(Ret.ok().set("num", n));
		} else {
			renderJson(Ret.fail());
		}
	}
	
	public void move() {
		Long cid = getParaToLong("cid");
		Long pid = getParaToLong("pid");
		String ids = getPara("ids");
		if(cid==null) {
			renderJson(Ret.fail().set("msg", "cid is null"));
			return;
		}
		if(pid==null) {
			renderJson(Ret.fail().set("msg", "pid is null"));
			return;
		}
		if(StrKit.isBlank(ids)) {
			renderJson(Ret.fail().set("msg", "ids is null"));
			return;
		}
		int n = MetaFileCatalogMapping.service().moveFile(cid, pid, ids);
		if(n > 0) {
			renderJson(Ret.ok().set("num", n));
		} else {
			renderJson(Ret.fail());
		}
	}

	
	/**
	 * 判断上传
	 */
	public void uploadSect() {
		DiskFileItemFactory factory = new DiskFileItemFactory();
    	ServletFileUpload sfu = new ServletFileUpload(factory);
    	sfu.setHeaderEncoding("utf-8");
    	
    	String savePath = PathKit.getWebRootPath() + "\\uploadFile\\";
    	
    	String fileMd5 = null;
    	String chunk = null;
    	
    	try {
			List<FileItem> items = sfu.parseRequest(getRequest());
			
			for(FileItem item:items){
				if(item.isFormField()){
					String fieldName = item.getFieldName();
					if(fieldName.equals("fileMd5")){
						fileMd5 = item.getString("utf-8");
					}
					if(fieldName.equals("chunk")){
						chunk = item.getString("utf-8");
					}
				}else{
					File file = new File(savePath+"/"+fileMd5);
					if(!file.exists()){
						file.mkdir();
					}
					File chunkFile = new File(savePath+"/"+fileMd5+"/"+chunk);
					FileUtils.copyInputStreamToFile(item.getInputStream(), chunkFile);
					
				}
			}
			
		} catch (FileUploadException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	renderJson(Ret.ok());
	}
	
	/**
	 * 上传结果
	 * @throws IOException
	 */
	public void upload() throws IOException {
        String savePath = PathKit.getWebRootPath() + "\\uploadFile\\";
        
		String action = getPara("action");
		
		if(action.equals("mergeChunks")){
			//合并文件
			//需要合并的文件的目录标记
			String fileMd5 = getPara("fileMd5");
			String fileName = getPara("fileName");
			String sufffix = fileName != null && fileName.contains(".") ? fileName.substring(fileName.lastIndexOf(".")) : null;
			//String path = "/uploadFile/" + fileMd5 + sufffix;
			
			Long catalogId = getParaToLong("catalogId");
					
			//读取目录里的所有文件
			File f = new File(savePath+"/"+fileMd5);
			File[] fileArray = f.listFiles(new FileFilter(){
				//排除目录只要文件
				@Override
				public boolean accept(File pathname) {
					// TODO Auto-generated method stub
					if(pathname.isDirectory()){
						return false;
					}
					return true;
				}
			});
			
			//转成集合，便于排序
			List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
			Collections.sort(fileList,new Comparator<File>() {
				@Override
				public int compare(File o1, File o2) {
					// TODO Auto-generated method stub
					if(Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())){
						return -1;
					}
					return 1;
				}
			});
			//UUID.randomUUID().toString()-->随机名
			File outputFile = new File(savePath+"/"+fileMd5+".mp4");
			//创建文件
			outputFile.createNewFile();
			//输出流
			FileChannel outChnnel = new FileOutputStream(outputFile).getChannel();
			//合并
			FileChannel inChannel;
			for(File file : fileList){
				inChannel = new FileInputStream(file).getChannel();
				inChannel.transferTo(0, inChannel.size(), outChnnel);
				inChannel.close();
				//删除分片
				file.delete();
			}
			outChnnel.close();
			//清除文件夹
			File tempFile = new File(savePath+"/"+fileMd5);
			if(tempFile.isDirectory() && tempFile.exists()){
				tempFile.delete();
			}
			System.out.println("合并成功");
			
			Long fileSize = outputFile.length();
			String newPath = AttachmentUtils.moveMetaFile(outputFile, "file", fileMd5 + sufffix);
			newPath = newPath.replaceAll("\\", "/");
			MetaFile attachment = new MetaFile();
			// attachment.setUserId();
			attachment.setCreated(new Date());
			attachment.setTitle(fileName);
			attachment.setPath(newPath);
			attachment.setSuffix(sufffix);
			//attachment.setMimeType(uploadFile.getContentType());
			attachment.setFilesize(fileSize);
			attachment.save();
			if(catalogId!=null) {
				MetaFileCatalogMappingService folderService = MetaFileCatalogMapping.service();
				folderService.save(attachment.getId(), catalogId);
			}
			String fileurl = getSystemPath() + newPath;
			renderJson(Ret.ok().set("fileurl", fileurl));
		} else if(action.equals("checkChunk")){
			//检查当前分块是否上传成功
			String fileMd5 = getPara("fileMd5");
			String chunk = getPara("chunk");
			String chunkSize = getPara("chunkSize");
			
			File checkFile = new File(savePath+"/"+fileMd5+"/"+chunk);
			
			//检查文件是否存在，且大小是否一致
			if(checkFile.exists() && checkFile.length()==Integer.parseInt(chunkSize)){
				//上传过
				renderJson(Ret.ok());
			}else{
				//没有上传过
				//response.getWriter().write("{\"ifExist\":0}");
				renderJson(Ret.fail());
			}
		}
	}
}
